package com.bridgeintelligent.tag.bulkload.service.core.chain;

import com.bridgeintelligent.tag.bulkload.api.BulkLoadConfig;
import com.bridgeintelligent.tag.bulkload.service.core.iterator.BulkListIterator;
import com.bridgeintelligent.tag.bulkload.service.core.threadpool.ThreadPoolExecutor;
import com.bridgeintelligent.tag.bulkload.service.es.ESUtils;
import com.bridgeintelligent.tag.constants.bulkload.BulkLoadMqMsg;
import com.bridgeintelligent.tag.mapper.EsIndexNameMapper;
import com.bridgeintelligent.tag.remotefile.RemoteFileHandler;
import com.bridgeintelligent.tag.remotefile.freedim.IDimFreeFileUtils;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by JackCheung on 2019/9/20 5:26 PM.
 */
@Getter
@Setter
@Component
@Slf4j
public abstract class BaseLoadChainTempleHandler {

    private int msgType;
    private RemoteFileHandler remoteFileHandler;
    @Autowired
    private EsIndexNameMapper esIndexNameMapper;
    @Autowired
    ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    IDimFreeFileUtils iDimFreeFileUtils;
    private String delFieldFormat = "ctx._source.remove(\"%s\")";
    private static final String SUB_SIGN = "|";
    protected static final String INDEX_SIGN = "03";
private static final String[] ECIF_INCLUDES = new String[]{BulkLoadConfig.ONE_ID};

    BaseLoadChainTempleHandler() {
    }

    public void loadHandler(BulkLoadMqMsg bulkLoadMqMsg) {
        //获取数组
        List<String> list;
        try {
            //bulkLoadMqMsg.getFilePath().replace(".txt",".ok")
            list = getFileList(chooseFilePath(bulkLoadMqMsg.getFilePath()), bulkLoadMqMsg.isEcifFlag());
        } catch (IOException e) {
            e.printStackTrace();
            log.error("\n读取文件异常----------", e);
            throw new RuntimeException(e);
        }
        BulkListIterator listIterator = createIterator(list);
        //根据主题id获取索引名
        String indexName = esIndexNameMapper.findIndexName("1");
        //处理消息
        loadHook(listIterator, bulkLoadMqMsg, indexName);
    }

    private String chooseFilePath(String filePath) {
        String result = filePath.replace(".txt", ".ok");
        File file = new File(result);
        return file.exists() ? result : filePath;
    }

    public void loadHook(BulkListIterator listIterator, BulkLoadMqMsg bulkLoadMqMsg, String indexName) {
    }

    private BulkListIterator createIterator(List<String> list) {
        return new BulkListIterator<>(list);
    }

    private List<String> getFileList(String filePath, boolean ecifFlag) throws IOException {
        if (!new File(filePath).exists()) {
            log.error("file not exists:" + filePath);
            return new ArrayList<>();
        }
        Set<String> set = new HashSet<>();
        try (BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath))) ) {
            String s;
            while ((s = br.readLine()) != null) {
                String value = s.replaceAll("\uFEFF", "");
                set.add(value);
            }
        }
        /*
        if (ecifFlag) {
            return fetchRealCustList(set);
        } else {
            return new ArrayList<>(set);
        }
        */
        return convertIdCode( ecifFlag, set );
    }

    /*
    private List<String> fetchRealCustList(Set<String> set) {
        int QUERY_MAX_SIZE = 100;
        List<String> ecifList = new ArrayList<>(set);
        List<String> result = new ArrayList<>(set.size());
        int maxSize = set.size();
        int count = maxSize % QUERY_MAX_SIZE == 0 ? maxSize / QUERY_MAX_SIZE : maxSize / QUERY_MAX_SIZE + 1;
        for (int i = 1; i <= count; i++) {
            int start = QUERY_MAX_SIZE * (i - 1);
            int end =start+QUERY_MAX_SIZE;
            end = Math.min(end, maxSize);
            List<String> tmpList = new ArrayList<>(end - start);
            Map<String, String> tmpMap = new HashMap<>(end - start);
            for (int j = start; j < end; j++) {
                tmpList.add(StringUtils.substringBefore(ecifList.get(j), SUB_SIGN));
                tmpMap.put(StringUtils.substringBefore(ecifList.get(j), SUB_SIGN),
                           StringUtils.substringAfter(ecifList.get(j), SUB_SIGN));
            }
            result.addAll(ESUtils.multiSearchDoc(tmpList, BulkLoadConfig.ECIF_INDEX_NAME, ECIF_INCLUDES)
                                 .entrySet()
                                 .stream()
                                 .map(s -> s.getKey() + SUB_SIGN + tmpMap.get(s.getValue()))
                                 .collect(Collectors.toList()));
        }
        return result;
    }
    */

    private List<String> convertIdCode( boolean isUserFlag, Set<String> userIdSet ) {
        int QUERY_MAX_SIZE = 100;
        List<String> userIds = new ArrayList<>( userIdSet );
        List<String> oneIds = new ArrayList<>( userIdSet.size() );
        int maxSize = userIdSet.size();
        int count = maxSize % QUERY_MAX_SIZE == 0 ? maxSize / QUERY_MAX_SIZE : maxSize / QUERY_MAX_SIZE + 1;
        for (int i = 1; i <= count; i++) {
            int start = QUERY_MAX_SIZE * (i - 1);
            int end =start+QUERY_MAX_SIZE;
            end = Math.min(end, maxSize);
            List<String> tmpList = new ArrayList<>(end - start);
            Map<String, String> tmpMap = new HashMap<>(end - start);
            for (int j = start; j < end; j++) {
                tmpList.add(StringUtils.substringBefore(userIds.get(j), SUB_SIGN));
                tmpMap.put(StringUtils.substringBefore(userIds.get(j), SUB_SIGN),
                           StringUtils.substringAfter(userIds.get(j), SUB_SIGN));
            }
            String indexName = isUserFlag ? BulkLoadConfig.USERID_INDEX_NAME : BulkLoadConfig.CUSTID_INDEX_NAME;
            Map<String, String> map = ESUtils.multiSearchDoc(tmpList, indexName, ECIF_INCLUDES);
            List<String> list = map.entrySet()
                                   .stream()
                                   .map(s -> s.getKey() + SUB_SIGN + tmpMap.get(s.getValue()))
                                   .collect(Collectors.toList());
            oneIds.addAll( list );
        }
        return oneIds;
    }

    List<Map<String, Map<String, Object>>> list(List<String> list, String dimId) {
        int size = list.size();
        List<Map<String, Map<String, Object>>> result = new ArrayList<>();
        for (int i = 1; i <= BulkLoadConfig.THREAD_COUNT; i++) {
            Map<String, Map<String, Object>> map = new HashMap<>(size / BulkLoadConfig.THREAD_COUNT);
            int start = size / BulkLoadConfig.THREAD_COUNT * (i - 1);
            int end = size * i / BulkLoadConfig.THREAD_COUNT;
            for (int j = start; j < end; j++) {
                Map<String, Object> dimValueMap = new HashMap<>(16);
                dimValueMap.put(dimId, StringUtils.substringAfter(list.get(j), SUB_SIGN));
                map.put(StringUtils.substringBefore(list.get(j), SUB_SIGN), dimValueMap);
            }
            result.add(map);
        }
        return result;
    }

    List<Map<String, String>> delList(List<String> list, String dimId) {
        int size = list.size();
        List<Map<String, String>> result = new ArrayList<>();
        String delStatement = String.format(delFieldFormat, dimId);
        for (int i = 1; i <= BulkLoadConfig.THREAD_COUNT; i++) {
            Map<String, String> map = new HashMap<>(size / BulkLoadConfig.THREAD_COUNT);
            int start = size / BulkLoadConfig.THREAD_COUNT * (i - 1);
            int end = size * i / BulkLoadConfig.THREAD_COUNT;
            for (int j = start; j < end; j++) {
                map.put(list.get(j), delStatement);
            }
            result.add(map);
        }
        return result;
    }
}
